﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using FBProject.BusinessLogic;
using FBProject.BusinessLogic.FBImport;
using FBProject.BusinessLogic.MSProjectProxies;

namespace FBProject
{
    public partial class FSynchronizationProgress : Form
    {
        private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(FSynchronizationProgress));

        private string FBFileName { get; set; }
        private DateTime OperationStart { get; set; }
        private TaskSynchronizer TaskSynchronizer { get; set; }
        public IList<TaskDifference> TaskDifferences { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "fb")]
        public FSynchronizationProgress(string fbFileName)
        {
            InitializeComponent();

            this.FBFileName = fbFileName;
            this.TaskSynchronizer = new TaskSynchronizer(new MSProjectProxy(MSProjectApplicationProxy.GetMSProjectApplication()), 20, 100);
            this.TaskSynchronizer.ProgressChanged += new ProgressChangedEventHandler(taskSynchronizer_ProgressChanged);
        }

        private void FProgress_Load(object sender, EventArgs e)
        {
            this.OperationStart = DateTime.UtcNow;
            this.OperationDurationUpdaterTimer.Start();
            this.SynchronizeBackgroundWorker.RunWorkerAsync();
        }

        private void SynchronizeBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            this.SynchronizeBackgroundWorker.ReportProgress(0, "Reading external tasks from CSV");
            IDictionary<string, ExternalTask> externalTasks;
            //using (var fbCsvImporter = new FBCsvImport(this.FBFileName))
            //{
            //    externalTasks = fbCsvImporter.ReadExternalTasksFromCsv();
            //}

            var fbImporter = new FBDBImport();
            externalTasks = fbImporter.ReadExternalTasks();

            if (!this.SynchronizeBackgroundWorker.CancellationPending)
            {
                TaskDifferences = this.TaskSynchronizer.Synchronize(externalTasks);
            }

            if (this.SynchronizeBackgroundWorker.CancellationPending)
            {
                e.Cancel = true;
            }

            this.SynchronizeBackgroundWorker.ReportProgress(100, "Finished");
        }

        void taskSynchronizer_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.SynchronizeBackgroundWorker.ReportProgress(e.ProgressPercentage, e.UserState.ToString());
        }

        private void SynchronizeBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var progressDescription = e.UserState.ToString();
            if (this.ProgressLabel.Text != progressDescription)
            {
                Logger.DebugFormat("Synchronization ({0}%) - {1}", e.ProgressPercentage, progressDescription);
            }
            this.ProgressBar.Value = e.ProgressPercentage;
            this.ProgressLabel.Text = progressDescription;
        }

        private void SynchronizeBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.OperationDurationUpdaterTimer.Stop();

            if (e.Error != null)
            {
                Logger.Error(e.Error.Message, e.Error);
                MessageBox.Show(e.Error.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                DialogResult = System.Windows.Forms.DialogResult.Abort;
            }
            else if (e.Cancelled)
            {
                MessageBox.Show("Operation was canceled", "INFO", MessageBoxButtons.OK, MessageBoxIcon.Information);
                DialogResult = System.Windows.Forms.DialogResult.Cancel;
            }
            else
            {
                DialogResult = System.Windows.Forms.DialogResult.OK;
            }
            Close();
        }

        private void CancelOperationButton_Click(object sender, EventArgs e)
        {
            this.SynchronizeBackgroundWorker.CancelAsync();
            this.TaskSynchronizer.Cancel();
            this.CancelOperationButton.Enabled = false;
        }

        private void OperationDurationUpdaterTimer_Tick(object sender, EventArgs e)
        {
            this.OperationDurationLabel.Text = (DateTime.UtcNow - this.OperationStart).ToString("hh\\:mm\\:ss");
        }

        private static void SaveDifferencesIntoFile(StreamWriter tempFileHandler, IList<TaskDifference> taskDifferences, TaskDifferenceType taskDifferenceType)
        {
            var selectedDifferences = ((List<TaskDifference>)taskDifferences).FindAll(td => td.DifferenceType == taskDifferenceType);
            if ((selectedDifferences != null) && (selectedDifferences.Count > 0))
            {
                tempFileHandler.WriteLine(taskDifferenceType.ToString().ToUpperInvariant());
                foreach (var taskDifference in selectedDifferences)
                {
                    tempFileHandler.WriteLine("\t{0}", taskDifference.FBCaseDescription);
                    if ((taskDifferenceType != TaskDifferenceType.NewTask) && (taskDifferenceType != TaskDifferenceType.DeletedTask))
                    {
                        tempFileHandler.WriteLine("\t\t{0} <> {1}", taskDifference.MSProjectValue, taskDifference.ExternalValue);
                    }
                }
                tempFileHandler.WriteLine(string.Empty);
            }
        }

    }
}
